//#include <athread.h>
#include <slave.h>
//#include "dma.h"
#include <signal.h>
extern long cgid;
#define IO_GET(addr) (*(long*)(addr))
#define CPE_BASE_ADDR(cpe_id) (0x8003000000L | cgid << 36L | cpe_id << 16L)
#define CPE_PC_ADDR 0x2000

inline long get_cpe_pc(int cpe_id){
  //return *(long*)(0x8003002000L | cgid << 36L | cpe_id << 16L);
  //return *(long*) CPE_BASE_ADDR(cpe_id) | CPE_PC_ADDR;
  return IO_GET(CPE_BASE_ADDR(cpe_id) | CPE_PC_ADDR);
}
#define TC_BASE_ADDR      (0x8004000000L | cgid << 36L)
#define TC_SDLB_ERR_PEVEC      0x308000L
#define TC_SDLB_ERR_SPOT       0x308080L
char *SDLB_REQ_TYPE_STR[] = {"read", "write", "faa", "updt+", "updt-"};
char *SDLB_REQ_SRC_STR[] = {"cpe", "ibox", "dma"};
char *BOOL_STR[] = {"no", "yes"};
inline void decode_sdlb_err(){
  puts("==============DECODE OF SDLB ERROR SPOT==============");
  long spot = IO_GET(TC_BASE_ADDR | TC_SDLB_ERR_SPOT);
  printf("TC_SDLB_ERR_SPOT: %lx\n", spot);
  long reqtype = spot & 7;
  printf("REQ_TYPE: %s\n", SDLB_REQ_TYPE_STR[reqtype]);
  long src_pe = spot >> 40 & 63;
  printf("SRC_PE: %d\n", src_pe);
  long grain = spot >> 46 & 2;
  printf("GRAIN: %d\n", 1 << grain);
  long src_id = spot >> 59 & 3;
  printf("SRC_TYPE: %s\n", SDLB_REQ_SRC_STR[src_id - 1]);
  long oor = (spot >> 61) & 1;
  printf("OUT_OF_RANGE: %s\n", BOOL_STR[oor]);
  long oop = (spot >> 62) & 1;
  printf("OUT_OF_PERM: %s\n", BOOL_STR[oop]);
}
#define GC_BASE_ADDR      (0x8005000000L | cgid << 36L)
#define GC_DMACHK_TYPE         0x200700L
char *DMA_ERR_STR[] = {
  "LDM unaligned",
  "MEM unaligned",
  "size unaligned",
  "bsize unaligned",
  "stride unaligned",
  "GET_P/PUT_P occur",
  "size non positive",
  "",
  "invalid OP",
  "invalid MODE",
  "invalid OP+MODE",
  "reply overflow/unaligned",
  "LDM overflow",
  "bcast vec=0",
  "not connected"
};
/*
void decode_dma_chk(){
  puts("================DECODE OF DMACHK_TYPE================");
  long chk = IO_GET(GC_BASE_ADDR | GC_DMACHK_TYPE);
  long type;
  puts("CHK_TYPE:");
  for (type = 0; type <= 14; type ++)
    if ((1 << type) & chk){
      printf("\t%s\n", DMA_ERR_STR[type]);
    }
  long src_pe = chk >> 16 & 63;
  printf("SRC_PE: %d\n", src_pe);
}
*/
void expt_decoder(int sig){
  printf("writing cpe PCs on signal %d\n", sig);
  int i, j;
  for (i = 0; i < 8; i ++) {
    for (j = 0; j < 8; j ++)
      printf("%3d: %12llx ", i * 8 + j, get_cpe_pc(i * 8 + j));
    puts("");
  }
  decode_sdlb_err();
  //decode_dma_chk();
}

/*
void slave_gid(long *_id){
  long cid;
  asm ("rcsr %0, 0\n\t": "=r"(cid));

  if (!_MYID){
    *_id = cid >> 6;
  }
}

void sig_init(int rank){
  if (!athread_idle())
    athread_init();

  long cid;
  athread_spawn(gid, &cid);
  athread_join();
  cgid = cid;
}
*/

void __wrap___expt_handler(void *a, void *b){
  expt_decoder(0);
  __expt_handler(a, b);
}
